import { Notification, INotification } from '../models/Notification';
import { User } from '../models/User';
import mongoose from 'mongoose';
import { logger } from '../utils/logger';

export interface NotificationData {
  recipientId?: string;
  senderId?: string;
  type: INotification['type'];
  title: string;
  content: string;
  relatedModel?: INotification['relatedModel'];
  relatedId?: string;
}

export class NotificationService {
  /**
   * 创建单个通知
   */
  static async create(data: NotificationData): Promise<INotification | null> {
    try {
      const notification = new Notification({
        recipient: data.recipientId,
        sender: data.senderId,
        type: data.type,
        title: data.title,
        content: data.content,
        relatedModel: data.relatedModel,
        relatedId: data.relatedId
      });

      await notification.save();
      logger.info('通知已创建', { 
        notificationId: notification._id, 
        type: data.type,
        recipient: data.recipientId 
      });
      
      return notification;
    } catch (error) {
      logger.error('创建通知失败', { error, data });
      return null;
    }
  }

  /**
   * 批量创建通知（给多个用户发送相同通知）
   */
  static async createBatch(recipientIds: string[], data: Omit<NotificationData, 'recipientId'>): Promise<void> {
    try {
      const notifications = recipientIds.map(recipientId => ({
        recipient: recipientId,
        sender: data.senderId,
        type: data.type,
        title: data.title,
        content: data.content,
        relatedModel: data.relatedModel,
        relatedId: data.relatedId,
        isRead: false
      }));

      await Notification.insertMany(notifications);
      logger.info('批量通知已创建', { 
        count: recipientIds.length,
        type: data.type 
      });
    } catch (error) {
      logger.error('批量创建通知失败', { error });
    }
  }

  /**
   * 给所有用户发送通知（除了发送者）
   */
  static async notifyAllUsers(data: NotificationData & { excludeUserId?: string }): Promise<void> {
    try {
      // 获取所有用户（排除发送者）
      const query: any = {};
      if (data.excludeUserId) {
        query._id = { $ne: data.excludeUserId };
      }
      
      const users = await User.find(query).select('_id');
      const recipientIds = users.map(user => (user._id as any).toString());

      if (recipientIds.length > 0) {
        await this.createBatch(recipientIds, data);
      }
    } catch (error) {
      logger.error('发送全体通知失败', { error });
    }
  }

  /**
   * 获取用户的通知列表
   */
  static async getUserNotifications(
    userId: string,
    limit: number = 20,
    skip: number = 0,
    unreadOnly: boolean = false
  ): Promise<INotification[]> {
    try {
      const query: any = { recipient: userId };
      if (unreadOnly) {
        query.isRead = false;
      }

      const notifications = await Notification.find(query)
        .sort({ createdAt: -1 })
        .limit(limit)
        .skip(skip)
        .populate('sender', 'name avatar')
        .lean();

      return notifications;
    } catch (error) {
      logger.error('获取用户通知失败', { error, userId });
      throw error;
    }
  }

  /**
   * 获取未读通知数量
   */
  static async getUnreadCount(userId: string): Promise<number> {
    try {
      const count = await Notification.countDocuments({
        recipient: userId,
        isRead: false
      });
      return count;
    } catch (error) {
      logger.error('获取未读通知数量失败', { error, userId });
      return 0;
    }
  }

  /**
   * 标记通知为已读
   */
  static async markAsRead(notificationId: string, userId: string): Promise<boolean> {
    try {
      const result = await Notification.updateOne(
        { 
          _id: notificationId,
          recipient: userId 
        },
        { 
          isRead: true,
          readAt: new Date()
        }
      );

      return result.modifiedCount > 0;
    } catch (error) {
      logger.error('标记通知已读失败', { error, notificationId, userId });
      return false;
    }
  }

  /**
   * 标记所有通知为已读
   */
  static async markAllAsRead(userId: string): Promise<void> {
    try {
      await Notification.updateMany(
        { 
          recipient: userId,
          isRead: false 
        },
        { 
          isRead: true,
          readAt: new Date()
        }
      );

      logger.info('已标记所有通知为已读', { userId });
    } catch (error) {
      logger.error('标记所有通知已读失败', { error, userId });
    }
  }

  /**
   * 删除通知
   */
  static async delete(notificationId: string, userId: string): Promise<boolean> {
    try {
      const result = await Notification.deleteOne({
        _id: notificationId,
        recipient: userId
      });

      return result.deletedCount > 0;
    } catch (error) {
      logger.error('删除通知失败', { error, notificationId, userId });
      return false;
    }
  }

  /**
   * 清理旧通知（保留最近30天）
   */
  static async cleanOldNotifications(): Promise<void> {
    try {
      const thirtyDaysAgo = new Date();
      thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

      const result = await Notification.deleteMany({
        createdAt: { $lt: thirtyDaysAgo },
        isRead: true
      });

      logger.info('清理旧通知完成', { deleted: result.deletedCount });
    } catch (error) {
      logger.error('清理旧通知失败', { error });
    }
  }
}